home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / Mesa-1.2.1 / src-glu / quadric.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-05  |  13.2 KB  |  550 lines

  1. /* quadric.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: quadric.c,v 1.6 1995/05/22 16:56:20 brianp Exp $
  26.  
  27. $Log: quadric.c,v $
  28.  * Revision 1.6  1995/05/22  16:56:20  brianp
  29.  * Release 1.2
  30.  *
  31.  * Revision 1.5  1995/05/16  19:17:21  brianp
  32.  * minor changes to allow compilation with real OpenGL headers
  33.  *
  34.  * Revision 1.4  1995/04/28  14:38:15  brianp
  35.  * moved GLUquadricObj struct from .h to .c file
  36.  *
  37.  * Revision 1.3  1995/04/18  15:51:41  brianp
  38.  * implemented gluPartialDisk()
  39.  * implemented quadric error handler
  40.  *
  41.  * Revision 1.2  1995/03/04  19:39:18  brianp
  42.  * version 1.1 beta
  43.  *
  44.  * Revision 1.1  1995/02/24  15:45:01  brianp
  45.  * Initial revision
  46.  *
  47.  */
  48.  
  49.  
  50. #include <math.h>
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include "gluP.h"
  54.  
  55.  
  56.  
  57. #define PI 3.14159
  58.  
  59.  
  60. /*
  61.  * Convert degrees to radians:
  62.  */
  63. #define DEG_TO_RAD(A)   ((A)*(PI/180.0))
  64.  
  65.  
  66. /*
  67.  * Sin and Cos for degree angles:
  68.  */
  69. #define SIND( A )   sin( (A)*(PI/180.0) )
  70. #define COSD( A)    cos( (A)*(PI/180.0) )
  71.  
  72.  
  73.  
  74. struct GLUquadricObj {
  75.     GLUenum    DrawStyle;        /* GLU_FILL, LINE, SILHOUETTE, or POINT */
  76.     GLUenum Orientation;        /* GLU_INSIDE or GLU_OUTSIDE */
  77.     GLboolean TextureFlag;        /* Generate texture coords? */
  78.     GLUenum Normals;        /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
  79.     void (*ErrorFunc)(GLUenum err);    /* Error handler callback function */
  80. };
  81.  
  82.  
  83.  
  84. /*
  85.  * Process a GLU error.
  86.  */
  87. static void quadric_error( GLUquadricObj *qobj, GLUenum error, const char *msg )
  88. {
  89.    /* Call the error call back function if any */
  90.    if (qobj->ErrorFunc) {
  91.       (*qobj->ErrorFunc)( error );
  92.    }
  93.    /* Print a message to stdout if MESA_DEBUG variable is defined */
  94.    if (getenv("MESA_DEBUG")) {
  95.       fprintf(stderr,"GLUError: %s: %s\n", gluErrorString(error), msg );
  96.    }
  97. }
  98.  
  99.  
  100.  
  101.  
  102. GLUquadricObj *gluNewQuadric( void )
  103. {
  104.    GLUquadricObj *q;
  105.  
  106.    q = (GLUquadricObj *) malloc( sizeof(struct GLUquadricObj) );
  107.    if (q) {
  108.       q->DrawStyle = GLU_FILL;
  109.       q->Orientation = GLU_OUTSIDE;
  110.    }
  111.    return q;
  112. }
  113.  
  114.  
  115.  
  116. void gluDeleteQuadric( GLUquadricObj *state )
  117. {
  118.    if (state) {
  119.       free( (void *) state );
  120.    }
  121. }
  122.  
  123.  
  124.  
  125. /*
  126.  * Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE, or GLU_POINT.
  127.  */
  128. void gluQuadricDrawStyle( GLUquadricObj *quadObject, GLUenum drawStyle )
  129. {
  130.    if (quadObject && (drawStyle==GLU_FILL || drawStyle==GLU_LINE
  131.            || drawStyle==GLU_SILHOUETTE || drawStyle==GLU_POINT)) {
  132.       quadObject->DrawStyle = drawStyle;
  133.    }
  134.    else {
  135.       quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle" );
  136.    }
  137. }
  138.  
  139.  
  140.  
  141. /*
  142.  * Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
  143.  */
  144. void gluQuadricOrientation( GLUquadricObj *quadObject, GLUenum orientation )
  145. {
  146.    if (quadObject && (orientation==GLU_INSIDE || orientation==GLU_OUTSIDE)) {
  147.       quadObject->Orientation = orientation;
  148.    }
  149.    else {
  150.       quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation" );
  151.    }
  152. }
  153.  
  154.  
  155.  
  156. /*
  157.  * Set the error handler callback function.
  158.  */
  159. void gluQuadricCallback( GLUquadricObj *qobj,
  160.              GLUenum which, void (*fn)() )
  161. {
  162.    if (qobj && fn && which==GLU_ERROR) {
  163.       qobj->ErrorFunc = fn;
  164.    }
  165. }
  166.  
  167.  
  168. void gluQuadricNormals( GLUquadricObj *quadObject, GLUenum normals )
  169. {
  170.    if (quadObject
  171.          && (normals==GLU_NONE || normals==GLU_FLAT || normals==GLU_SMOOTH)) {
  172.       quadObject->Normals = normals;
  173.    }
  174. }
  175.  
  176.  
  177. void gluQuadricTexture( GLUquadricObj *quadObject,
  178.                 GLboolean textureCoords )
  179. {
  180.    if (quadObject) {
  181.       quadObject->TextureFlag = textureCoords;
  182.    }
  183. }
  184.  
  185.  
  186. void gluCylinder( GLUquadricObj *qobj,
  187.                   GLdouble baseRadius, GLdouble topRadius, GLdouble height,
  188.                   GLint slices, GLint stacks )
  189. {
  190.    GLdouble a, da;
  191.    GLfloat x, y, nz;
  192.  
  193.    da = 2.0*PI / slices;
  194.  
  195.    if (qobj->DrawStyle==GLU_FILL) {
  196.       glBegin( GL_QUAD_STRIP );
  197.    }
  198.    else if (qobj->DrawStyle==GLU_LINE) {
  199.       glBegin( GL_LINES );
  200.    }
  201.    else if (qobj->DrawStyle==GLU_SILHOUETTE) {
  202.       glBegin( GL_LINES );
  203.    }
  204.    else if (qobj->DrawStyle==GLU_POINT) {
  205.       glBegin( GL_POINTS );
  206.    }
  207.  
  208.    nz = (baseRadius-topRadius) / height;
  209.    for (a=0.0; a<2.0*PI; a+=da) {
  210.       x = cos(a);
  211.       y = sin(a);
  212.  
  213.       glNormal3f( x, y, nz );
  214.       glVertex3f( x*topRadius, y*topRadius, height );
  215.       glVertex3f( x*baseRadius, y*baseRadius, 0.0 );
  216.    }
  217.    glNormal3f( 1.0, 0.0, nz );
  218.    glVertex3f( topRadius, 0.0, height );
  219.    glVertex3f( baseRadius, 0.0, 0.0 );
  220.    glEnd();
  221.  
  222.    if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
  223.       /* Draw end circles */
  224.       glBegin( GL_LINE_LOOP );
  225.       for (a=0.0; a<2.0*PI; a+=da) {
  226.          x = cos(a) * topRadius;
  227.          y = sin(a) * topRadius;
  228.          glVertex3f( x, y, height );
  229.       }
  230.       glEnd();
  231.       glBegin( GL_LINE_LOOP );
  232.       for (a=0.0; a<2.0*PI; a+=da) {
  233.          x = cos(a) * baseRadius;
  234.          y = sin(a) * baseRadius;
  235.          glVertex3f( x, y, 0.0 );
  236.       }
  237.       glEnd();
  238.    }
  239. }
  240.  
  241.  
  242.  
  243.  
  244. void gluSphere( GLUquadricObj *qobj,
  245.                 GLdouble radius, GLint slices, GLint stacks )
  246. {
  247.    /* TODO: implement GLU_LINE, GLU_SILHOUETTE, etc. */
  248.  
  249.    GLfloat rho, drho, theta, dtheta;
  250.    GLfloat x, y, z;
  251.    GLint i, j;
  252.  
  253.    drho = PI / (GLfloat) stacks;
  254.    dtheta = 2.0 * PI / (GLfloat) slices;
  255.  
  256.    /* loop over stacks */
  257.    rho = -PI/2.0;
  258.    for (i=0;i<stacks;i++) {
  259.       glBegin( GL_QUAD_STRIP );
  260.  
  261.       /* loop over slices */
  262.       theta = 0.0;
  263.       for (j=0;j<slices+1;j++) {
  264.  
  265.      if (j==slices) {
  266.         theta = 0.0;
  267.      }
  268.  
  269.      x = cos(theta) * cos(rho+drho);
  270.      y = sin(theta) * cos(rho+drho);
  271.      z = sin(rho+drho);
  272.          glNormal3f( x, y, z );
  273.      glVertex3f( x*radius, y*radius, z*radius );
  274.  
  275.          x = cos(theta) * cos(rho);
  276.      y = sin(theta) * cos(rho);
  277.      z = sin(rho);
  278.      glNormal3f( x, y, z );
  279.      glVertex3f( x*radius, y*radius, z*radius );
  280.  
  281.      theta += dtheta;
  282.       }
  283.       glEnd();
  284.       rho += drho;
  285.    }
  286. }
  287.  
  288.  
  289.  
  290. void gluDisk( GLUquadricObj *qobj,
  291.               GLdouble innerRadius, GLdouble outerRadius,
  292.               GLint slices, GLint loops )
  293. {
  294.    GLdouble a, da;
  295.    GLfloat r, dr;
  296.    GLfloat x, y;
  297.    GLfloat r1, r2;
  298.    GLint s, l;
  299.  
  300.    /* Normal vectors */
  301.    if (qobj->Normals!=GLU_NONE) {
  302.       if (qobj->Orientation==GLU_OUTSIDE) {
  303.      glNormal3f( 0.0, 0.0, +1.0 );
  304.       }
  305.       else {
  306.      glNormal3f( 0.0, 0.0, -1.0 );
  307.       }
  308.    }
  309.  
  310.    da = 2.0*PI / slices;
  311.    dr = (outerRadius-innerRadius) / (GLfloat) loops;
  312.  
  313.    switch (qobj->DrawStyle) {
  314.       case GLU_FILL:
  315.          r1 = innerRadius;
  316.          for (l=0;l<loops;l++) {
  317.         r2 = r1 + dr;
  318.         glBegin( GL_QUAD_STRIP );
  319.         a = 0.0;
  320.         for (s=0;s<slices-1;s++) {
  321.            glVertex2f( r1*sin(a), r1*cos(a) );
  322.            glVertex2f( r2*sin(a), r2*cos(a) );
  323.            a += da;
  324.         }
  325.         glVertex2f( 0.0, r1 );
  326.         glVertex2f( 0.0, r2 );
  327.         glEnd();
  328.         r1 = r2;
  329.      }
  330.          break;
  331.       case GLU_LINE:
  332.      /* draw rings */
  333.      for (r=innerRadius; r<=outerRadius; r+=dr) {
  334.         glBegin( GL_LINE_LOOP );
  335.         for (a=0.0; a<2.0*PI; a+=da) {
  336.            glVertex2f( r*sin(a), r*cos(a) );
  337.         }
  338.         glEnd();
  339.      }
  340.      /* draw spokes */
  341.      for (a=0.0; a<2.0*PI; a+=da) {
  342.         x = sin(a);
  343.         y = cos(a);
  344.         glBegin( GL_LINE_STRIP );
  345.         for (r=innerRadius; r<=outerRadius; r+=dr) {
  346.            glVertex2f( r*x, r*y );
  347.         }
  348.         glEnd();
  349.      }
  350.      break;
  351.       case GLU_POINT:
  352.      glBegin( GL_POINTS );
  353.      for (a=0.0; a<2.0*PI; a+=da) {
  354.         x = sin(a);
  355.         y = cos(a);
  356.         for (r=innerRadius; r<=outerRadius; r+=dr) {
  357.            glVertex2f( r*x, r*y );
  358.         }
  359.      }
  360.      glEnd();
  361.      break;
  362.       case GLU_SILHOUETTE:
  363.      if (innerRadius!=0.0) {
  364.         glBegin( GL_LINE_LOOP );
  365.         for (a=0.0; a<2.0*PI; a+=da) {
  366.            x = innerRadius * sin(a);
  367.            y = innerRadius * cos(a);
  368.            glVertex2f( x, y );
  369.         }
  370.         glEnd();
  371.      }
  372.      glBegin( GL_LINE_LOOP );
  373.      for (a=0; a<2.0*PI; a+=da) {
  374.         x = outerRadius * sin(a);
  375.         y = outerRadius * cos(a);
  376.         glVertex2f( x, y );
  377.      }
  378.      glEnd();
  379.      break;
  380.    }
  381.  
  382.    /* Draw interior */
  383.    if (qobj->DrawStyle!=GLU_SILHOUETTE) {
  384.       if (qobj->DrawStyle==GLU_FILL) {
  385.          glBegin( GL_QUAD_STRIP );
  386.       }
  387.       else if (qobj->DrawStyle==GLU_LINE) {
  388.          glBegin( GL_LINES );
  389.       }
  390.       else if (qobj->DrawStyle==GLU_POINT) {
  391.          glBegin( GL_POINTS );
  392.       }
  393.       for (a=0.0; a<2.0*PI; a+=da) {
  394.          x = sin(a);
  395.          y = cos(a);
  396.  
  397.          glVertex2f( x*innerRadius, y*innerRadius );
  398.          glVertex2f( x*outerRadius, y*outerRadius );
  399.       }
  400.       glVertex2f( 0.0, innerRadius );
  401.       glVertex2f( 0.0, outerRadius );
  402.       glEnd();
  403.    }
  404.  
  405.    /* Draw circles */
  406.    if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
  407.       if (innerRadius!=0.0) {
  408.          /* Draw inner circle */
  409.          glBegin( GL_LINE_LOOP );
  410.          for (a=0.0; a<2.0*PI; a+=da) {
  411.             x = sin(a) * innerRadius;
  412.             y = cos(a) * innerRadius;
  413.             glVertex2f( x, y );
  414.      }
  415.          glEnd();
  416.       }
  417.       /* Draw outer circle */
  418.       glBegin( GL_LINE_LOOP );
  419.       for (a=0.0; a<2.0*PI; a+=da) {
  420.          x = sin(a) * outerRadius;
  421.          y = cos(a) * outerRadius;
  422.          glVertex2f( x, y );
  423.       }
  424.       glEnd();
  425.    }
  426.  
  427. }
  428.  
  429.  
  430.  
  431. void gluPartialDisk( GLUquadricObj *qobj, GLdouble innerRadius,
  432.              GLdouble outerRadius, GLint slices, GLint loops,
  433.              GLdouble startAngle, GLdouble sweepAngle )
  434. {
  435.    if (qobj->Normals!=GLU_NONE) {
  436.       if (qobj->Orientation==GLU_OUTSIDE) {
  437.      glNormal3f( 0.0, 0.0, +1.0 );
  438.       }
  439.       else {
  440.      glNormal3f( 0.0, 0.0, -1.0 );
  441.       }
  442.    }
  443.  
  444.    if (qobj->DrawStyle==GLU_POINT) {
  445.       GLint loop, slice;
  446.       GLdouble radius, delta_radius;
  447.       GLdouble angle, delta_angle;
  448.       delta_radius = (outerRadius - innerRadius) / (loops-1);
  449.       delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1));
  450.       glBegin( GL_POINTS );
  451.       radius = innerRadius;
  452.       for (loop=0; loop<loops; loop++) {
  453.      angle = DEG_TO_RAD(startAngle);
  454.      for (slice=0; slice<slices; slice++) {
  455.         glVertex2d( radius * sin(angle), radius * cos(angle) );
  456.         angle += delta_angle;
  457.      }
  458.      radius += delta_radius;
  459.       }
  460.       glEnd();
  461.    }
  462.    else if (qobj->DrawStyle==GLU_LINE) {
  463.       GLint loop, slice;
  464.       GLdouble radius, delta_radius;
  465.       GLdouble angle, delta_angle;
  466.       delta_radius = (outerRadius - innerRadius) / (loops-1);
  467.       delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1));
  468.       /* draw rings */
  469.       radius = innerRadius;
  470.       for (loop=0; loop<loops; loop++) {
  471.      angle = DEG_TO_RAD(startAngle);
  472.      glBegin( GL_LINE_STRIP );
  473.      for (slice=0; slice<slices; slice++) {
  474.         glVertex2d( radius * sin(angle), radius * cos(angle) );
  475.         angle += delta_angle;
  476.      }
  477.      glEnd();
  478.      radius += delta_radius;
  479.       }
  480.       /* draw spokes */
  481.       angle = DEG_TO_RAD(startAngle);
  482.       for (slice=0; slice<slices; slice++) {
  483.      radius = innerRadius;
  484.      glBegin( GL_LINE_STRIP );
  485.      for (loop=0; loop<loops; loop++) {
  486.         glVertex2d( radius * sin(angle), radius * cos(angle) );
  487.         radius += delta_radius;
  488.      }
  489.      glEnd();
  490.      angle += delta_angle;
  491.       }
  492.    }
  493.    else if (qobj->DrawStyle==GLU_SILHOUETTE) {
  494.       GLint slice;
  495.       GLdouble angle, delta_angle;
  496.       delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1));
  497.       /* draw outer ring */
  498.       glBegin( GL_LINE_STRIP );
  499.       angle = DEG_TO_RAD(startAngle);
  500.       for (slice=0; slice<slices; slice++) {
  501.      glVertex2d( outerRadius * sin(angle), outerRadius * cos(angle) );
  502.      angle += delta_angle;
  503.       }
  504.       glEnd();
  505.       /* draw inner ring */
  506.       if (innerRadius>0.0) {
  507.      glBegin( GL_LINE_STRIP );
  508.      angle = DEG_TO_RAD(startAngle);
  509.      for (slice=0; slice<slices; slice++) {
  510.         glVertex2d( innerRadius * sin(angle), innerRadius * cos(angle) );
  511.         angle += delta_angle;
  512.      }
  513.      glEnd();
  514.       }
  515.       /* draw spokes */
  516.       if (sweepAngle<360.0) {
  517.      GLdouble stopAngle = startAngle + sweepAngle;
  518.      glBegin( GL_LINES );
  519.      glVertex2d( innerRadius*SIND(startAngle), innerRadius*COSD(startAngle) );
  520.      glVertex2d( outerRadius*SIND(startAngle), outerRadius*COSD(startAngle) );
  521.      glVertex2d( innerRadius*SIND(stopAngle), innerRadius*COSD(stopAngle) );
  522.      glVertex2d( outerRadius*SIND(stopAngle), outerRadius*COSD(stopAngle) );
  523.      glEnd();
  524.       }
  525.    }
  526.    else if (qobj->DrawStyle==GLU_FILL) {
  527.       GLint loop, slice;
  528.       GLdouble radius, delta_radius;
  529.       GLdouble angle, delta_angle;
  530.       delta_radius = (outerRadius - innerRadius) / (loops-1);
  531.       delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1));
  532.       radius = innerRadius;
  533.       for (loop=0; loop<loops-1; loop++) {
  534.      glBegin( GL_QUAD_STRIP );
  535.      angle = DEG_TO_RAD(startAngle);
  536.      for (slice=0; slice<slices; slice++) {
  537.         glVertex2d( radius * sin(angle), radius * cos(angle) );
  538.         glVertex2d( (radius+delta_radius)*sin(angle),
  539.                 (radius+delta_radius)*cos(angle) );
  540.         angle += delta_angle;
  541.      }
  542.      glEnd();
  543.      radius += delta_radius;
  544.       }
  545.  
  546.  
  547.    }
  548. }
  549.  
  550.